package com.aiyan.edu.framework.canary.loadbalancer;

import com.aiyan.edu.framework.canary.context.CanaryContextHolder;
import com.google.common.base.Optional;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 根据灰度标签定向选择服务实例返回
 *
 * @author: zqzhou
 * @create: 2019/12/04 17:47
 **/
public class CanaryMetadataBasedRole extends ZoneAvoidanceRule {

    @Override
    public Server choose(Object key) {

        //获取所有缓存服务列表
        List<Server> eligibleServers = super.getPredicate().getEligibleServers(super.getLoadBalancer().getAllServers(), key);

        if (null == eligibleServers || eligibleServers.size() == 0) {
            return null;
        }

        //获取请求是否是来自灰度【用户或者IP等】
        String canaryFlag = CanaryContextHolder.getCanaryContext();

        //是灰度请求，则转发到灰度服务
        //如果不是灰度请求，按照默认负载均衡策略转发到非灰度服务

        List<Server> nonCanaryServers = new ArrayList<>();

        for (Server server : eligibleServers) {
            Map<String, String> metadata = ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata();
            // 是否是灰度服务  判断是否有灰度标签
            String meta = metadata.get(CanaryContextHolder.CANARY_META_KEY);
            if (meta != null) {
                // 如果是灰度服务并且与请求的灰度标签值相同，则直接返回
                // 灰度服务应该只有一个（一个服务一个灰度实例）
                if (meta.equals(canaryFlag)) {
                    System.err.println(canaryFlag + " - " + ((DiscoveryEnabledServer) server).getInstanceInfo().getInstanceId());
                    return server;
                }
            } else {
                nonCanaryServers.add(server);
            }
        }

        if (!StringUtils.isEmpty(canaryFlag) || nonCanaryServers.isEmpty()) {
            return null;
        }

        //非灰度请求
        Optional<Server> serverOptional = super.getPredicate().chooseRoundRobinAfterFiltering(nonCanaryServers, key);
        if (!serverOptional.isPresent()) {
            return null;
        }

        System.err.println(((DiscoveryEnabledServer) serverOptional.get()).getInstanceInfo().getInstanceId());
        return serverOptional.get();
    }
}
